package com.zhu.array;

/**
 * 对Java提供的数组再次封装，实现动态的改变长度
 * @author: zhu
 * @date: 2019/1/10 11:58
 */
public class Array<E>{

    private E[] data;//存储数据的数组
    private int size;//数组中元素的个数

    /** 构造函数，capacity表示数组的容量，即length */
    public Array(int capacity){
        data = (E[]) new Object[capacity];
        size = 0;
    }
    public Array(E[] arr){
        data = (E[]) new Object[arr.length];
        for (int i=0;i<arr.length;i++){
            data[i] = arr[i];
            size = arr.length;
        }
    }
    public Array(){
        this(10);
    }

    /** 获取数组中元素的个数 */
    public int getSize(){
        return size;
    }

    /** 获取数组的容量，即length */
    public int getCapacity(){
        return data.length;
    }

    /** 判断数组是否为空 */
    public boolean isEmpty(){
        return size == 0;
    }

    /** 往数组指定索引处添加元素 */
    public void add(int index,E e){
        if (index < 0 || index > size)
            throw new IllegalArgumentException("插入位置不合法");
        if (size == data.length)//数组已满
            resize(2 * data.length);//扩容两倍
        for (int i = size - 1;i >= index; i --){
            data[i+1] = data[i];
        }
        data[index] = e;
        size ++;
    }

    /** 往数组末尾添加元素 */
    public void addLast(E e){
        add(size,e);
    }

    /** 往数组第一个位置添加元素 */
    public void addFirst(E e){
        add(0,e);
    }

    /** 获取index位置的元素 */
    public E get(int index){
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("查询位置不合法");
        return data[index];
    }
    public E getLast(){
        return get(size - 1);
    }
    public E getFirst(){
        return get(0);
    }

    /** 修改index位置的元素 */
    public void update(int index,E e){
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("查询位置不合法");
        data[index] = e;
    }

    /** 查找数组中是否包含元素e */
    public boolean contains(E e){
        for (int i = 0; i < size; i++){
            if (data[i] .equals(e)) return true;
        }
        return false;
    }

    /** 查找元素e所在的索引 */
    public int find(E e){
        for (int i = 0; i < size; i++){
            if (data[i].equals(e)) return i;
        }
        return -1;
    }

    /** 删除index索引处的元素 */
    public E remove(int index){
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("查询位置不合法");
        E temp = data[index];
        for (int i = index + 1;i< size; i++){
            data[i-1] = data[i];
        }
        size --;
        data[size] = null;//这句话可有可无
        if (size == data.length/4 && data.length /2 != 0){//如果删除元素后数组只使用了1/4的容量
            resize(data.length/2);//那就缩小容量到以前的一半
        }
        return temp;
    }

    /** 删除数组中的第一个元素 */
    public E removeFirst(){
        return remove(0);
    }

    /** 删除数组中的最后一个元素 */
    public E removeLast(){
        return remove(size-1);
    }

    /** 删除指定元素e */
    public void removeElement(E e){
        int index = find(e);
        if (index != -1){
            remove(index);
        }
    }

    /** 交换两个元素的位置 */
    public void swap(int x,int y){
        if (x<0 || x>=size || y<0 || y>=size )
            throw new IllegalArgumentException("传入的索引不合法");
        E temp = data[x];
        data[x] = data[y];
        data[y] = temp;
    }

    /** 给数组扩容 */
    private void resize(int newCapacity) {
        E[] newData = (E[]) new Object[newCapacity];//新数组
        for (int i = 0; i< size;i++){
            newData[i] = data[i];//旧数组的值存入新数组对应的位置
        }
        data = newData;//指向新数组
    }
    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append(String.format("size = %d,capacity = %d\n",size,data.length));
        res.append("[");
        for (int i = 0;i < size; i++){
            res.append(data[i]);
            if (i != size -1){
                res.append(", ");
            }
        }
        res.append("]");
        return res.toString();
    }
}
